package org.nstack.header.storage.primary;

import org.nstack.header.query.*;
import org.nstack.header.storage.snapshot.VolumeSnapshotInventory;
import org.nstack.header.configuration.PythonClassInventory;
import org. nstack.header.query.*;
import org.nstack.header.search.Inventory;
import org.nstack.header.search.TypeField;
import org.nstack.header.volume.VolumeInventory;
import org.nstack.header.zone.ZoneInventory;

import javax.persistence.JoinColumn;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


@Inventory(mappingVOClass = PrimaryStorageVO.class)
@PythonClassInventory
@ExpandedQueries({
        @ExpandedQuery(expandedField = "zone", inventoryClass = ZoneInventory.class,
                foreignKey = "zoneUuid", expandedInventoryKey = "uuid"),
        @ExpandedQuery(expandedField = "volume", inventoryClass = VolumeInventory.class,
                foreignKey = "uuid", expandedInventoryKey = "primaryStorageUuid"),
        @ExpandedQuery(expandedField = "volumeSnapshot", inventoryClass = VolumeSnapshotInventory.class,
                foreignKey = "uuid", expandedInventoryKey = "primaryStorageUuid"),
        @ExpandedQuery(expandedField = "clusterRef", inventoryClass = PrimaryStorageClusterRefInventory.class,
                foreignKey = "uuid", expandedInventoryKey = "primaryStorageUuid", hidden = true),
})
@ExpandedQueryAliases({
        @ExpandedQueryAlias(alias = "cluster", expandedField = "clusterRef.cluster")
})
public class PrimaryStorageInventory implements Serializable {

    private String uuid;

    private String zoneUuid;

    private String name;

    private String url;

    private String description;

    @Queryable(mappingClass = PrimaryStorageCapacityInventory.class,
            joinColumn = @JoinColumn(name = "uuid", referencedColumnName = "totalCapacity"))
    private Long totalCapacity;

    @Queryable(mappingClass = PrimaryStorageCapacityInventory.class,
            joinColumn = @JoinColumn(name = "uuid", referencedColumnName = "availableCapacity"))
    private Long availableCapacity;

    @Queryable(mappingClass = PrimaryStorageCapacityInventory.class,
            joinColumn = @JoinColumn(name = "uuid", referencedColumnName = "totalPhysicalCapacity"))
    private Long totalPhysicalCapacity;

    @Queryable(mappingClass = PrimaryStorageCapacityInventory.class,
            joinColumn = @JoinColumn(name = "uuid", referencedColumnName = "availablePhysicalCapacity"))
    private Long availablePhysicalCapacity;

    @Queryable(mappingClass = PrimaryStorageCapacityInventory.class,
            joinColumn = @JoinColumn(name = "uuid", referencedColumnName = "systemUsedCapacity"))
    private Long systemUsedCapacity;


    @TypeField
    private String type;

    private String state;

    private String status;


    private String mountPath;

    private Timestamp createDate;

    private Timestamp lastOpDate;

    @Queryable(mappingClass = PrimaryStorageClusterRefInventory.class,
            joinColumn = @JoinColumn(name = "primaryStorageUuid", referencedColumnName = "clusterUuid"))
    private List<String> attachedClusterUuids;

    public PrimaryStorageInventory() {
    }

    protected PrimaryStorageInventory(PrimaryStorageVO vo) {
        setZoneUuid(vo.getZoneUuid());
        setCreateDate(vo.getCreateDate());
        setDescription(vo.getDescription());
        setLastOpDate(vo.getLastOpDate());
        setName(vo.getName());
        setState(vo.getState().toString());
        setType(vo.getType());
        setUrl(vo.getUrl());
        setUuid(vo.getUuid());
        setMountPath(vo.getMountPath());
        setStatus(vo.getStatus().toString());
        attachedClusterUuids = new ArrayList<String>(vo.getAttachedClusterRefs().size());
        for (PrimaryStorageClusterRefVO ref : vo.getAttachedClusterRefs()) {
            attachedClusterUuids.add(ref.getClusterUuid());
        }

        if (vo.getCapacity() != null) {
            setTotalCapacity(vo.getCapacity().getTotalCapacity());
            setAvailableCapacity(vo.getCapacity().getAvailableCapacity());
            setTotalPhysicalCapacity(vo.getCapacity().getTotalPhysicalCapacity());
            setAvailablePhysicalCapacity(vo.getCapacity().getAvailablePhysicalCapacity());
            setSystemUsedCapacity(vo.getCapacity().getSystemUsedCapacity());
        }
    }

    public Long getSystemUsedCapacity() {
        return systemUsedCapacity;
    }

    public void setSystemUsedCapacity(Long systemUsedCapacity) {
        this.systemUsedCapacity = systemUsedCapacity;
    }

    public static PrimaryStorageInventory valueOf(PrimaryStorageVO vo) {
        return new PrimaryStorageInventory(vo);
    }

    public static List<PrimaryStorageInventory> valueOf(Collection<PrimaryStorageVO> vos) {
        List<PrimaryStorageInventory> invs = new ArrayList<PrimaryStorageInventory>(vos.size());
        for (PrimaryStorageVO vo : vos) {
            invs.add(PrimaryStorageInventory.valueOf(vo));
        }
        return invs;
    }

    public Long getTotalPhysicalCapacity() {
        return totalPhysicalCapacity;
    }

    public void setTotalPhysicalCapacity(Long totalPhysicalCapacity) {
        this.totalPhysicalCapacity = totalPhysicalCapacity;
    }

    public Long getAvailablePhysicalCapacity() {
        return availablePhysicalCapacity;
    }

    public void setAvailablePhysicalCapacity(Long availablePhysicalCapacity) {
        this.availablePhysicalCapacity = availablePhysicalCapacity;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public long getAvailableCapacity() {
        return availableCapacity;
    }

    public void setAvailableCapacity(long availableCapacity) {
        this.availableCapacity = availableCapacity;
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public long getTotalCapacity() {
        return totalCapacity;
    }

    public void setTotalCapacity(long totalCapacity) {
        this.totalCapacity = totalCapacity;
    }

    public Timestamp getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Timestamp createDate) {
        this.createDate = createDate;
    }

    public Timestamp getLastOpDate() {
        return lastOpDate;
    }

    public void setLastOpDate(Timestamp lastOpDate) {
        this.lastOpDate = lastOpDate;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public List<String> getAttachedClusterUuids() {
        return attachedClusterUuids;
    }

    public void setAttachedClusterUuids(List<String> attachedClusterUuids) {
        this.attachedClusterUuids = attachedClusterUuids;
    }

    public String getMountPath() {
        return mountPath;
    }

    public void setMountPath(String mountPath) {
        this.mountPath = mountPath;
    }

    public String getZoneUuid() {
        return zoneUuid;
    }

    public void setZoneUuid(String zoneUuid) {
        this.zoneUuid = zoneUuid;
    }
}
